<?php
/*
 * @Author: lokei
 * @Date: 2022-08-16 13:16:33
 * @LastEditors: lokei
 * @LastEditTime: 2023-10-24 19:53:52
 * @Description: 
 */

namespace App\Http\Controllers\Pay\Weixin;

use App\Common\Tools\ResultTool;
use App\Common\Tools\Sn;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Pay\Weixin\Init;
use App\Models\Pay\ConfModel;
use App\Models\Pay\Record\PayRecordModel;
use App\Models\Platform\Conf\ConfMiniappModel;
use App\Models\Platform\ConfModel as PlatformConfModel;
use App\Models\Store\StoreModel;
use Illuminate\Http\Request;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;

class JsapiController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }


    //
    public function pay(Request $request)
    {
        $user = app('auth')->user();
        $store_id = 0;
        if ($request->input('order_id') != null && intval($request->input('order_id')) > 0) {
            if ($request->input('mode') == '3') { // 储值卡开通
            } else if ($request->input('mode') == '1') { // 充值

            } else if ($request->input('store_id') != null && intval($request->input('store_id')) > 0) {
                $store = StoreModel::where('id', '=', $request->input('store_id'))->first();
                if ($store->wxpay_platform_certs != null && $store->wxpay_platform_certs != '') {
                    $store_id = $request->input('store_id');
                    $pay_conf = $store;
                }
            }
        }
        if (!isset($pay_conf)) {
            $pay_conf = ConfModel::first();
        }
        $instance = Init::getInstance($store_id);
        if (config('app.proj_identity') != null && config('app.proj_identity') != '') {
            $appid = $request->header('appid');
        } else {
            $miniapp_conf = ConfMiniappModel::first();
            $appid = $miniapp_conf->appid;
        }
        $sn = Sn::build_order_no();
        $pay_record = new PayRecordModel();
        $pay_record->store_id = $store_id > 0 ? $store_id : (intval($request->input('store_id')) > 0 ? intval($request->input('store_id')) : 0);
        $pay_record->uid = $user->uid;
        $pay_record->mode = $request->input('mode');
        $pay_record->pay_mode = '1';
        $pay_record->tid = $sn;
        $pay_record->order_id = $request->input('order_id');
        $pay_record->money = $request->input('money');
        $pay_record->status = '0';
        $pay_record->createtime = date('Y-m-d H:i:s', time());
        $pay_record->save();
        $pay_description = '';
        if ($request->input('description') != null && $request->input('description') != '') {
            $pay_description = $request->input('description');
        } else {
            $platform_conf = PlatformConfModel::first();
            $pay_description = $platform_conf->name . '支付';
        }
        $notify_url = env('HOST_URL') . ((env('HOST_PORT') != null && intval(env('HOST_PORT')) > 0) ? (':' . env('HOST_PORT')) : '') . '/api/pay/wx/notify';
        if (config('app.proj_identity') != null && config('app.proj_identity') != '') {
            $notify_url .= '/' . config('app.proj_identity');
        } else {
            $notify_url .= '/0';
        }
        if ($store_id > 0) {
            $notify_url .= '/' . $store_id;
        } else {
            $notify_url .= '/0';
        }
        if ($store_id > 0 && $pay_conf->profitsharing_on == '1') {
            $json_params = [
                'mchid'        => $pay_conf->mchid,
                'out_trade_no' => $sn,
                'appid'        => $appid,
                'description'  => $pay_description,
                'notify_url'   => $notify_url,
                'amount'       => [
                    'total'    => floatVal($request->input('money')) * 100,
                    'currency' => 'CNY'
                ],
                'payer' => [
                    'openid' => $request->input('openid')
                ],
                'settle_info' => [
                    'profit_sharing' => true
                ]
            ];
        } else {
            $json_params = [
                'mchid'        => $pay_conf->mchid,
                'out_trade_no' => $sn,
                'appid'        => $appid,
                'description'  => $pay_description,
                'notify_url'   => $notify_url,
                'amount'       => [
                    'total'    => intval(floatVal($request->input('money')) * 100),
                    'currency' => 'CNY'
                ],
                'payer' => [
                    'openid' => $request->input('openid')
                ]
            ];
        }

        try {
            $resp = $instance
                ->v3->pay->transactions->jsapi
                ->post(['json' => $json_params]);
            $jsapi_result = json_decode($resp->getBody()->getContents());
            // 从本地文件中加载「商户API私钥」，「商户API私钥」会用来生成请求的签名
            $merchantPrivateKeyFilePath = 'file://' . env('ATTACHMENT_ROOT') . $pay_conf->key_file;
            $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
            $params = [
                'appId'     => $appid,
                'timeStamp' => (string)Formatter::timestamp(),
                'nonceStr'  => Formatter::nonce(),
                'package'   => 'prepay_id=' . $jsapi_result->prepay_id,
            ];
            $params += ['paySign' => Rsa::sign(
                Formatter::joinedByLineFeed(...array_values($params)),
                $merchantPrivateKeyInstance
            ), 'signType' => 'RSA'];
            unset($params['appId']);
            $res = ResultTool::success();
            $res['data'] = $params;
            return $res;
        } catch (\Exception $e) {
            // 进行错误处理
            app('log')->info($e->getMessage());
            if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
                $r = $e->getResponse();
                app('log')->info($r->getStatusCode() . ' ' . $r->getReasonPhrase());
                app('log')->info($r->getBody());
            }
            app('log')->info($e->getTraceAsString());
            $res = ResultTool::fail();
            $res['errorMsg'] = $e;
            return $res;
        }
    }
}
